﻿using GN.Pay.TradeChannel.AliPay.Request;
using GN.Pay.TradeChannel.AliPay.Response;
using GN.Pay.TradeChannel.Configure;
using GN.Pay.TradeChannel.DefaultImpl;
using GN.Pay.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GN.Pay.TradeChannel.AliPay
{
    /// <summary>
    /// 支付宝服务基础
    /// </summary>
    [Serializable]
    public abstract class AliPayServiceBase : ATradeChannel<IDictionary<string, string>>
    {
        protected readonly AliPayConfigure channelConfigure;

        protected AliPayServiceBase()
        {
            this.channelConfigure = new AliPayConfigure(this);
        }

        public sealed override ITradeChannelConfigure ChannelConfigure
        {
            get
            {
                return this.channelConfigure;
            }
        }

        public sealed override Type TradeChannelConfigureInfoType
        {
            get
            {
                return typeof(AiliPayConfigureInfo);
            }
        }

        /// <summary>
        /// 获取提供者全称
        /// </summary>
        public sealed override string ChannelProvider
        {
            get
            {
                return "支付宝(中国)网络技术有限公司";
            }
        }

        /// <summary>
        /// 退款申请
        /// </summary>
        /// <param name="apply"></param>
        /// <returns></returns>
        public sealed override ITradeRefundApplyResult RefundApply(IRefundApplyInfo apply)
        {
            var config = this.channelConfigure;
            var request = RefundRequest.CreateRequest(this, apply, config);
            var response = request.Build(this, config, apply);
            return response.ToResult();
        }

        private static IChannel TempChannel = TradeChannelInfo.Create("AliPay", "支付宝");


        /// <summary>
        /// 获取付款的订单号
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string GetPayOrderNo(IDictionary<string, string> message)
        {
            if (message == null || message.Count == 0)
            {
                return null;
            }
            NotifyResponse response = new NotifyResponse(message);
            var entity = response.ToEntity<PayNotifyResponseEntity>();
            return entity.Out_Trade_No;
        }


        /// <summary>
        /// 获取退款批次号
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string GetRefundNo(IDictionary<string, string> message)
        {
            if (message == null || message.Count == 0)
            {
                return null;
            }
            NotifyResponse response = new NotifyResponse(message);
            var entity = response.ToEntity<RefundNotifyResponseEntity>();
            if (entity.IsSuccess())
            {
                var results = entity.ToRefundResults(TempChannel);
                if (results.Count > 0)
                {
                    return results[0].RefundNo;
                }
            }
            return null;
        }

        /// <summary>
        /// 订单付款通知响应
        /// </summary>
        /// <param name="message">消息</param>
        public PayNotifyResponseEntity OrderPayNotifyResponse(IDictionary<string, string> message)
        {
            NotifyResponse response = new NotifyResponse(message);
            if (!response.SignVeryfy(this, this.channelConfigure))
            {
                this.ThrowChannelValidationException("支付宝支付通知验签失败");
            }
            try
            {
                var entity = response.ToEntity<PayNotifyResponseEntity>();
                //if (string.IsNullOrWhiteSpace(entity.Trade_Status))
                //{
                //    this.ThrowChannelValidationException("支付宝交易付款通知交易状态为null或空白。");
                //}
                return entity;
            }
            catch (Exception e)
            {
                throw this.ThrowChannelValidationException("支付宝支付通知数据格式出错:" + e.Message);
            }
        }

        /// <summary>
        /// 支付宝即时到账参数处理,手机APP到账处理
        /// </summary>
        /// <param name="sercice"></param>
        /// <param name="message"></param>
        public sealed override void OrderPayNotify(INotifyService sercice,
            IDictionary<string, string> message)
        {
            var entity = OrderPayNotifyResponse(message);
            if (entity.IsSuccess())
            {
                var result = entity.ToPayResult(this);
                if (result != null)
                {
                    sercice.OrderPayNotify(result);
                }
            }
        }

        /// <summary>
        /// 退款通知
        /// </summary>
        /// <param name="sercice"></param>
        /// <param name="message"></param>
        public sealed override void OrderRefundNotify(INotifyService sercice,
            IDictionary<string, string> message)
        {
            NotifyResponse response = new NotifyResponse(message);
            if (!response.SignVeryfy(this, this.channelConfigure))
            {
                this.ThrowChannelValidationException("支付宝退款通知验签失败");
            }
            try
            {
                var entity = response.ToEntity<RefundNotifyResponseEntity>();
                if (entity.IsSuccess())
                {
                    var results = entity.ToRefundResults(this);
                    foreach (var result in results)
                    {
                        sercice.OrderRefundNotify(result);
                    }
                }
            }
            catch (Exception e)
            {
                this.ThrowChannelValidationException("支付宝退款通知数据格式出错:" + e.Message);
            }
        }

        public sealed override ITradeOrderQueryResult OrderSingleQuery(DateTime queryDate, string orderNo, string tradeNo)
        {
            if (string.IsNullOrWhiteSpace(orderNo) && string.IsNullOrWhiteSpace(tradeNo))
            {
                TradeChannelExceptionUtils.ThrowClientRequestException(this.ChannelId, "查询订单时，交易号或者订单号必须提供一项。");
            }
            var config = this.channelConfigure;
            var request = new QueryRequest(this, config, tradeNo, orderNo);
            var response = request.Build();
            return response.ToResult();
        }

        public sealed override string PayNotifyResponse(bool isSuccess)
        {
            if (isSuccess)
            {
                return "success";
            }
            return "fail";
        }

        public sealed override string RefundNotifyResponse(bool isSuccess)
        {
            if (isSuccess)
            {
                return "success";
            }
            return "fail";
        }
    }
}
